﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufConstants.h"
#include "GnufQtObjectPtr.h"

///////////////////////////////////////////////////////////////////////////////
// Use const_cast explicitly to reuse the constant method. Otherwise, the
// developer has to write the duplicated code with the constant method.
#define GNUF_INVOKE_CONST_METHOD(Class, Method) \
    const_cast< decltype( Method() ) >(              /* Get the inconstant type from the inconstant method. */ \
        ( static_cast< const Class * const >( this ) )->Method()); /* Call immediately the constant method. */

#define GNUF_INVOKE_CONST_METHOD_WITH_PARAMETER(Class, Method, Parameter) \
    const_cast< decltype( Method( Parameter ) ) >(              /* Get the inconstant type from the inconstant method. */ \
        ( static_cast< const Class * const >( this ) )->Method( Parameter )); /* Call immediately the constant method. */

#define GNUF_INVOKE_CONST_METHOD_WITH_PARAMETER2(Class, Method, Parameter, Parameter2) \
    const_cast< decltype( Method( Parameter, Parameter2 ) ) >(              /* Get the inconstant type from the inconstant method. */ \
        ( static_cast< const Class * const >( this ) )->Method( Parameter, Parameter2 )); /* Call immediately the constant method. */
        
#define GNUF_INVOKE_CONST_METHOD_WITH_PARAMETER3(Class, Method, Parameter, Parameter2, Parameter3) \
    const_cast< decltype( Method( Parameter, Parameter2, Parameter3 ) ) >(              /* Get the inconstant type from the inconstant method. */ \
        ( static_cast< const Class * const >( this ) )->Method( Parameter, Parameter2, Parameter3 )); /* Call immediately the constant method. */
//
///////////////////////////////////////////////////////////////////////////////

#define GNUF_PTR_IF_NULL_SKIP(Ptr, Invoke) \
    if ( auto Ptr = Invoke() ) Ptr
    
#define GNUF_CALL_IF_NULL_SKIP(Invoke) \
    if ( auto ptr = Invoke() ) ptr

#define GNUF_GET_PTR_IF_NULL_RETURN(Ptr, Invoke, Value) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return Value;

#define GNUF_GET_PTR_IF_NULL_RETURN_VOID(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return;

#define GNUF_GET_PTR_IF_NULL_RETURN_FALSE(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return false;

#define GNUF_GET_PTR_IF_NULL_RETURN_NULLPTR(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return nullptr;

#define GNUF_GET_PTR_IF_NULL_RETURN_EMPTY_WSTR(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return gcmp::ConstantsString::EmptyWStr;

#define GNUF_GET_PTR_IF_NULL_RETURN_EMPTY_STR(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) return gcmp::ConstantsString::EmptyStr;

#define GNUF_GET_PTR_IF_NULL_CONTINUE(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) continue;

#define GNUF_GET_PTR_IF_NULL_BREAK(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    if ( nullptr == Ptr ) break;

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_RETURN(Ptr, L"GMEP", Value) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_RETURN_UNLESS(nullptr != Ptr, Value, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_RETURN_VOID(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != Ptr, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_RETURN_FALSE(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_RETURN_FALSE_UNLESS(nullptr != Ptr, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_RETURN_NULLPTR(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_RETURN_FALSE_UNLESS(nullptr != Ptr, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_CONTINUE(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_CONTINUE_UNLESS(nullptr != Ptr, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");

#define GNUF_GET_PTR_IF_NULL_DBG_WARN_AND_BREAK(Ptr, Invoke) \
    auto Ptr = Invoke(); \
    DBG_WARN_AND_BREAK_UNLESS(nullptr != Ptr, L"The Invoke() returns a nullptr!", L"GMEP", L"2022-06-23");


// 
/////////////////////
// Qt New Utils

#define GNUF_NEW_AS_QT_AUTO_PTR_IF_NULL_RETURN_VOID(autoPtr, TYPE, ...) \
    static_assert(std::is_base_of<QObject, TYPE>::value, "Must inherit from QObject!"); \
    gcmp::QtAutoPtr<TYPE> autoPtr(NEW_AS_OWNER_PTR(TYPE, __VA_ARGS__)); \
    DBG_WARN_AND_RETURN_VOID_UNLESS(autoPtr.isValid(), L"The Qt Object has not been constructed successfully!", L"GMEP", L"2022-11-23");

#define GNUF_NEW_AS_QT_AUTO_PTR_IF_NULL_RETURN_FALSE(autoPtr, TYPE, ...) \
    static_assert(std::is_base_of<QObject, TYPE>::value, "Must inherit from QObject!"); \
    gcmp::QtAutoPtr<TYPE> autoPtr(NEW_AS_OWNER_PTR(TYPE, __VA_ARGS__)); \
    DBG_WARN_AND_RETURN_FALSE_UNLESS(autoPtr.isValid(), L"The Qt Object has not been constructed successfully!", L"GMEP", L"2022-11-23");

#define GNUF_NEW_AS_QT_AUTO_PTR_IF_NULL_RETURN_NULLPTR(autoPtr, TYPE, ...) \
    static_assert(std::is_base_of<QObject, TYPE>::value, "Must inherit from QObject!"); \
    gcmp::QtAutoPtr<TYPE> autoPtr(NEW_AS_OWNER_PTR(TYPE, __VA_ARGS__)); \
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(autoPtr.isValid(), L"The Qt Object has not been constructed successfully!", L"GMEP", L"2022-11-23");

#define GNUF_NEW_AS_QT_AUTO_PTR_IF_NULL_RETURN(autoPtr, returnVal, TYPE, ...) \
    static_assert(std::is_base_of<QObject, TYPE>::value, "Must inherit from QObject!"); \
    gcmp::QtAutoPtr<TYPE> autoPtr(NEW_AS_OWNER_PTR(TYPE, __VA_ARGS__)); \
    DBG_WARN_AND_RETURN_UNLESS(autoPtr.isValid(), returnVal, L"The Qt Object has not been constructed successfully!", L"GMEP", L"2022-11-23");
